package com.dji.compose_learning.ui.view

import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.colorResource
import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.text.SpanStyle
import androidx.compose.ui.unit.dp
import com.dji.compose_learning.R

/**
 * java关键字
 */
val CODE_KEY = listOf(
    "abstract", "assert", "boolean", "break", "byte",
    "case", "catch", "char", "class", "const",
    "continue", "default", "do", "double", "else",
    "enum", "extends", "final", "finally", "float",
    "for", "goto", "if", "implements", "import",
    "instanceof", "int", "interface", "long", "native",
    "new", "package", "private", "protected", "public",
    "return", "strictfp", "short", "static", "super",
    "switch", "synchronized", "this", "throw", "throws",
    "transient", "try", "void", "volatile", "while"
)

/**
 * 检查当前是否处于指定搜索项中，第一个参数为当前需要判定的搜索项
 * 返回 true ：处于当前搜索项中
 * 返回 false： 不处于当前搜索项中
 */
fun checkSearch(vararg searchLocations: Int): Boolean {
    if (searchLocations.size <= 1) {
        return true
    } else {
        if (searchLocations.fold(0) { acc, i -> acc + i } == -searchLocations.size ||
            searchLocations[0] >= 0) {
            return true
        }
        return false
    }
}

/**
 * 查找当前位置之前最近有效的class关键字
 */
fun findLastSymbolClass(index: Int, code: String): Int {
    if (index >= code.length || index < 0) {
        return -1
    }
    val lastIndex = code.substring(0, index).lastIndexOf("class")
    return if (lastIndex - 1 >= 0 && (code[lastIndex - 1] == ' '
                || code[lastIndex - 1] == '\t'
                || code[lastIndex - 1] == '\n') &&
        ((lastIndex + 5) < code.length && (code[lastIndex + 5] == ' '
                || code[lastIndex - 1] == '\t'
                || code[lastIndex - 1] == '\n'))
    ) {
        lastIndex
    } else {
        findLastSymbolClass(lastIndex, code)
    }
}

//function匹配正则表式
const val FUNCTION_MATCH_PATTERN = "<[\\s\\S]+>\\s*\\S*\\s+\\S*\\s*\\([\\s\\S]*\\)\\s*\\{"

//class匹配正则表达式
const val CLASS_MATCH_PATTERN = "\n|\\s*class\\s+\\S+\\s*<[\\s\\S]+>\\s*(extends\\s+\\S+)?\\s*\\{"
//class A<M extends String,K,S,P> extends File {

/**
 * 获取代码文本颜色配置
 */
@Composable
internal fun valuateCodeStyle(code: String): List<AnnotatedString.Range<SpanStyle>> {
    val spanList = mutableListOf<AnnotatedString.Range<SpanStyle>>()
    var keyStartLocation = -1         //扫描关键字起始位置
    var explainTextStart = -1         //扫描注释起始位置
    var explainMutiLineTextStart = -1 //扫描多行注释起始位置
    var annotationStart = -1          //扫描注释起始位置
    var stringStart = -1              //扫描代码中字符串(字符)（以避免标记字符串中的关键字、泛型等）

    val templateKeyFunctionArray = arrayListOf<String>() //当前function中需要解析的泛型字符数组
//    var checkingInFunction = false                       //标记当前是否在方法中
    var functionLeftBracket = 0  //方法退出标记 通过计数 '{' 判定方法结束位置
    var functionRightBracket = 0

//    var smallLeftBracket = 0  //排除小括号干扰（泛型函数解析和类解析）
//    var smallRightBracket = 0

    //数组长度标识当前进入了几层class嵌套
//    var checkingInClass = ArrayList<Boolean>()      //当前处于类解析中
//    var classTemplateStart = ArrayList<Int>()            //类泛型扫描
    var classLeftBracket = ArrayList<Int>()
    var classRightBracket = ArrayList<Int>()
    val templateKeyClassArray = arrayListOf<ArrayList<String>>() //当前class中需要解析的泛型字符数组

    code.toCharArray().forEachIndexed { index, ch ->
        //单行注释搜索
        if (checkSearch(explainTextStart,
                explainMutiLineTextStart,
                keyStartLocation,
                annotationStart,
                stringStart)
        ) {
            if (ch == '/' && index + 1 < code.length && code[index + 1] == '/') {
                if (explainTextStart == -1) {
                    explainTextStart = index
                }
            }
            if (explainTextStart >= 0 && ch == '\n') {
                if (explainTextStart >= 0) {
                    spanList.add(
                        AnnotatedString.Range(
                            SpanStyle(color = colorResource(id = R.color.code_explain_color)),
                            explainTextStart,
                            index))
                }
                explainTextStart = -1
            }
        }

        //多行注释搜做
        if (checkSearch(explainMutiLineTextStart,
                explainTextStart,
                keyStartLocation,
                annotationStart,
                stringStart)
        ) {
            if (ch == '/' && index + 1 < code.length && code[index + 1] == '*') { //检测到开始标记
                if (explainMutiLineTextStart == -1) {
                    explainMutiLineTextStart = index
                }
            }
            if (explainMutiLineTextStart >= 0 && ch == '/' && index > 0 && code[index - 1] == '*') {
                if (explainMutiLineTextStart >= 0) {
                    spanList.add(
                        AnnotatedString.Range(
                            SpanStyle(color = colorResource(id = R.color.code_explain_color)),
                            explainMutiLineTextStart,
                            index + 1))
                }
                explainMutiLineTextStart = -1
            }
        }

        //注释扫描
        if (checkSearch(annotationStart,
                keyStartLocation,
                explainTextStart,
                explainMutiLineTextStart,
                stringStart)
        ) {
            if (ch == '@') {
                if (annotationStart == -1) {
                    annotationStart = index
                }
            }
            if (annotationStart >= 0 && (ch == '\n' || ch == ' ' || ch == '(')) {
                if (annotationStart >= 0) {
                    spanList.add(
                        AnnotatedString.Range(
                            SpanStyle(color = colorResource(id = R.color.code_annotation_color)),
                            annotationStart,
                            index))
                }
                annotationStart = -1
            }
        }

        //字符串扫描
        if (checkSearch(stringStart,
                explainTextStart,
                explainMutiLineTextStart,
                annotationStart,
                keyStartLocation)
        ) {
            if (ch == '\"' || ch == '\'') {
                if (stringStart == -1) {
                    stringStart = index
                }
            }
            if (stringStart in 0 until index &&
                ((ch == '\"' && code[stringStart] == '\"') || (ch == '\'' && code[stringStart] == '\''))
            ) {
                if (stringStart < index - 1) {
                    spanList.add(
                        AnnotatedString.Range(
                            SpanStyle(color = colorResource(id = R.color.code_string_color)),
                            stringStart,
                            index + 1))
                }
                stringStart = -1
            }
        }

        //关键字扫描
        if (checkSearch(keyStartLocation,
                explainTextStart,
                explainMutiLineTextStart,
                annotationStart,
                stringStart)
        ) {
            // 小括号中不匹配泛型定义
//            if (ch == '(') {
//                smallLeftBracket++
//            }
//            if (ch == ')') {
//                smallRightBracket++
//                if (smallLeftBracket == smallRightBracket) {
//                    smallLeftBracket = 0
//                    smallRightBracket = 0
//                }
//            }

            //泛型类退出标记
            if (templateKeyClassArray.isNotEmpty()) {
                if (ch == '{') {
                    classLeftBracket[classLeftBracket.size - 1]++
                }

                if (ch == '}') {
                    classRightBracket[classRightBracket.size - 1]++
                    if (classLeftBracket.last() == classRightBracket.last()) { //标记类退出，清空类进入标记和类泛型记录
//                        checkingInClass.removeLast()
//                        classTemplateStart.removeLast()
                        classLeftBracket.removeLast()
                        classRightBracket.removeLast()
                        templateKeyClassArray.removeLast()
                    }
                }
            }

            //泛型方法退出标记
            if (functionLeftBracket > 0) {
                if (ch == '{') {
                    functionLeftBracket++
                }

                if (ch == '}') {
                    functionRightBracket++
                    if (functionLeftBracket == functionRightBracket) {
//                        checkingInFunction = false
                        functionLeftBracket = 0
                        functionRightBracket = 0
                        templateKeyFunctionArray.clear()
                    }
                }
            }

            //检测当前是否进入泛型方法
            if (ch == '{') {
                val classStartIndex = findLastSymbolClass(index, code)
                val classString =
                    if (classStartIndex >= 0) code.substring(classStartIndex, index + 1) else ""
                if (classString.indexOf('{') == classString.length - 1 &&
                    Regex(CLASS_MATCH_PATTERN).matches(classString)
                ) {
//                    classTemplateStart.add(-1) //标识进入类解析中，检测类泛型标记中
                    if (classLeftBracket.size > 0) {
                        classLeftBracket[classLeftBracket.size - 1]--
                    }
                    classLeftBracket.add(1)
                    classRightBracket.add(0)
                    templateKeyClassArray.add(ArrayList())

                    val templateStart = classString.indexOf('<') + 1
                    var ind = index - classString.length + templateStart + 1
                    classString.substring(templateStart, classString.indexOf('>')).split(",")
                        .filter { it.isNotBlank() }.forEach {
                            var arr: List<String> = if (it.contains("extends")) {
                                it.split("extends")
                            } else if (it.contains("super")) {
                                it.split("super")
                            } else {
                                listOf(it)
                            }
                            templateKeyClassArray.last().add(arr[0].trim())
                            spanList.add(
                                AnnotatedString.Range(
                                    SpanStyle(color = colorResource(id = R.color.code_template_color)),
                                    ind, ind + arr[0].length))
                            if (arr.size > 1 && templateKeyClassArray.flatten()
                                    .contains(arr[1].trim())
                            ) {
                                spanList.add(
                                    AnnotatedString.Range(
                                        SpanStyle(color = colorResource(id = R.color.code_template_color)),
                                        ind + it.lastIndexOf(' '), ind + it.length))
                            }
                            ind += it.length + 1
                        }
                }

                val functionStartIndex = code.substring(0, index).lastIndexOf('<')
                if (functionStartIndex >= 0) {
                    val funString = code.substring(functionStartIndex, index + 1)
                    //避免识别形如：if ((index < 0) || (index >= length())) { 这样的表达式
                    if (!funString.contains("(") &&
                        !funString.contains("[") &&
                        !funString.contains(")") &&
                        !funString.contains("]") &&
                        !funString.contains("!") &&
                        !funString.contains("&") &&
                        !funString.contains("|") &&
                        funString.indexOf('{') == funString.length - 1 &&
                        Regex(FUNCTION_MATCH_PATTERN).matches(funString)
                    ) {
//                        checkingInFunction = true
                        functionLeftBracket++

                        //记录当前泛型方法的泛型关键字
                        var ind = index - funString.length + 2
                        funString.substring(1, funString.indexOf('>')).split(",")
                            .filter { it.isNotBlank() }.forEach {
                                var arr: List<String> = if (it.contains("extends")) {
                                    it.split("extends")
                                } else if (it.contains("super")) {
                                    it.split("super")
                                } else {
                                    listOf(it)
                                }
                                templateKeyFunctionArray.add(arr[0].trim())
                                spanList.add(
                                    AnnotatedString.Range(
                                        SpanStyle(color = colorResource(id = R.color.code_template_color)),
                                        ind, ind + arr[0].length))
                                if (arr.size > 1 && (templateKeyFunctionArray.contains(arr[1].trim()) ||
                                            templateKeyClassArray.flatten()
                                                .contains(arr[1].trim()))
                                ) {
                                    spanList.add(
                                        AnnotatedString.Range(
                                            SpanStyle(color = colorResource(id = R.color.code_template_color)),
                                            ind + it.lastIndexOf(' '), ind + it.length))
                                }
                                ind += it.length + 1
                            }
                    }
                }

            }

            if (ch != ' ' && ch != '\t' && ch != '\n' &&
                ch != '(' && ch != '@' && ch != '[' &&
                ch != '_' && ch != '+' && ch != '-' && ch != '*' &&
                ch != ';' && ch != '{' && ch != '}' && ch != ')' &&
                ch != ']' && ch != '/' && ch != '|' && ch != '&' &&
                ch != '!' && ch != ',' && ch != '<' && ch != '>'
            ) {
                if (keyStartLocation == -1) {
                    keyStartLocation = index
                }
            }


            //关键字结束符检测
            if (ch == ' ' || ch == '\n' || ch == '\t' ||
                ch == '(' || ch == '<' || ch == ',' ||
                ch == ';' || ch == '>'
            ) {
                if (keyStartLocation != -1) {
                    val key = code.substring(keyStartLocation, index)
                    if (index >= keyStartLocation) {
                        if (CODE_KEY.contains(key)) { //java关键字
                            spanList.add(
                                AnnotatedString.Range(
                                    SpanStyle(color = colorResource(id = R.color.code_key_color)),
                                    keyStartLocation,
                                    index))
                        }
                        //类泛型、方法泛型关键字搜索
                        if ((templateKeyClassArray.isNotEmpty() &&
                                    templateKeyClassArray.flatten().contains(key)) ||
                            (templateKeyFunctionArray.isNotEmpty() &&
                                    templateKeyFunctionArray.contains(key))
                        ) {
                            spanList.add(
                                AnnotatedString.Range(
                                    SpanStyle(color = colorResource(id = R.color.code_template_color)),
                                    keyStartLocation,
                                    index))
                        }
                    }

                    //检测到类定义关键字
//                    if (key == "class") {
//
//                    }
                }
                keyStartLocation = -1
            }
        }
    }
    return spanList
}

@Composable
fun CodeView(code: String, modifier: Modifier = Modifier) {
    val annotatedString = AnnotatedString(code, valuateCodeStyle(code))
    Surface(modifier = modifier.padding(4.dp),
        color = MaterialTheme.colorScheme.background,
        shadowElevation = 2.dp,
        shape = RoundedCornerShape(4.dp)) {
        Text(text = annotatedString,
            modifier = Modifier
                .padding(10.dp),
            style = MaterialTheme.typography.bodyMedium,
            color = MaterialTheme.colorScheme.onBackground)
    }
}




















